/*
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
 */
package erwiki.plugins;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

import org.apache.log4j.Logger;
import org.elwiki_data.WikiPage;
import org.osgi.framework.FrameworkUtil;

import erwiki.Wiki;
import erwiki.api.WikiPartReference;
import erwiki.api.core.Engine;
import erwiki.api.core.WikiContext;
import erwiki.api.exceptions.PluginException;
import erwiki.api.exceptions.ProviderException;
import erwiki.api.pages.PageLock;
import erwiki.api.pages.PageManager;
import erwiki.api.plugin.PluginManager;
import erwiki.api.plugin.WikiPlugin;
import erwiki.api.preferences.Preferences;
import erwiki.util.TextUtil;

/**
 * Плагин ErWiki. Создает простой блог.
 * <p>
 * Параметры плагина:
 * <ul>
 * <li><b>entrytext</b> - текст ссылки.</li>
 * <li><b>page</b> - если задана, то запись добавляется на указанную страницу блога. По умолчанию
 * используется текущая страница.</li>
 * </ul>
 */
public class WeblogEntryPlugin implements WikiPlugin {

	private static final Logger log = Logger.getLogger(WeblogEntryPlugin.class);

	private static final int MAX_BLOG_ENTRIES = 10_000; // Just a precaution.

	/** Имя параметра для установки значения <i>entrytext</i>. Значение <tt>{@value}</tt>. */
	public static final String PARAM_ENTRYTEXT = "entrytext";

	/* Необязательный параметр: страница, которая фактически содержит блог.
	 * Это позволяет нам предоставить ссылку "new entry" на страницу блога где-то еще, а не на самой странице.
	 */
	// "page" для единообразного именования с помощью WeblogPlugin...

	/** Имя параметра для установки значения <i>page</i>. Значение <tt>{@value}</tt>. */
	public static final String PARAM_BLOGNAME = "page";

	@WikiPartReference
	private Engine engine;

	@WikiPartReference
	private PageManager pageManager;

	/**
	 * Возвращает новое имя страницы для записей. Просматривает список всех страниц блога и обнаруживает
	 * следующую в очереди.
	 *
	 * @param blogName Имя страницы (или блога).
	 *
	 * @return Новое имя.
	 * @throws ProviderException Если что-то пойдет не так.
	 */
	public String getNewEntryPage(String blogName) throws ProviderException {
		SimpleDateFormat fmt = new SimpleDateFormat(WeblogPlugin.DEFAULT_DATEFORMAT);
		String today = fmt.format(new Date());
		int entryNum = findFreeEntry(blogName, today);

		return WeblogPlugin.makeEntryPage(blogName, today, "" + entryNum);
	}

	/** {@inheritDoc} */
	@Override
	public String execute(WikiContext context, Map<String, String> params) throws PluginException {
		String weblogName = params.get(PARAM_BLOGNAME);
		if (weblogName == null) {
			weblogName = context.getPage().getName();
		}

		String entryText = TextUtil.replaceEntities(params.get(PARAM_ENTRYTEXT));
		if (entryText == null) {
			PluginManager pluginManager = context.getEngine().getManager(PluginManager.class);
			entryText = pluginManager.getString(Preferences.getLocale(), FrameworkUtil.getBundle(this.getClass()),
					"weblogentryplugin.newentry");
		}

		String url = null;
		try {
			url = context.getURL(WikiContext.PAGE_NONE, "NewBlogEntry.jsp", "page=" + engine.encodeName(weblogName));
		} catch (IOException e) {
			throw new PluginException(e.getMessage());
		}

		return "<a href=\"" + url + "\">" + entryText + "</a>";
	}

	private int findFreeEntry(String baseName, String date) throws ProviderException {
		Collection<WikiPage> everyone = pageManager.getAllPages();
		String startString = WeblogPlugin.makeEntryPage(baseName, date, "");
		int max = 0;

		for (WikiPage p : everyone) {
			if (p.getName().startsWith(startString)) {
				try {
					String probableId = p.getName().substring(startString.length());
					int id = Integer.parseInt(probableId);
					if (id > max) {
						max = id;
					}
				} catch (NumberFormatException e) {
					log.debug("Was not a log entry: " + p.getName());
				}
			}
		}

		// Найти первую страницу, на которой нет блокировки страницы.
		int idx = max + 1;
		while (idx < MAX_BLOG_ENTRIES) {
			WikiPage page = Wiki.page(WeblogPlugin.makeEntryPage(baseName, date, Integer.toString(idx)));
			PageLock lock = pageManager.getCurrentLock(page);
			if (lock == null) {
				break;
			}

			idx++;
		}

		return idx;
	}

}
